/*
 * SD_SPI.c
 *˵úΪͨSDд⺯
 * 			 ûֻҪġSD_HardWare.cеײ룬ֲκδϡ
 *  Created on: 2013-3-4
 *      Author: Administrator
 */
#include"SD_HardWare.h"
#include "SD_SPI.h"
#include"SPI.h"

//-----SD ص궨-----
#define SD_WRITE_DELAY				100				// ȷ74ϵʱ
#define SD_EMPTY_CLK				0xFF
#define SD_EMPTY_DATA				0xFF
#define SD_SPI_CRC						0xFF				//SPIģʽCRCЧ
#define SD_CMD0_CRC					0x95				//λCMD0CRCУ
#define SD_CMD0 						0+0x40		//λ
#define SD_CMD1 						1+0x40		//SPIģʽ
#define SD_CMD17 						17+0x40		//
#define SD_CMD24						24+0x40		//д
#define SD_CMD41						41+0x40		//ʼ
#define SD_CMD55						55+0x40		//ʼ
#define SD_CMD59                        59+0x40

//-----SDӦ-----
#define SD_COMMAND_ACK		0x00   			//Ӧ
#define SD_RESET_ACK					0x01				//λӦ
#define SD_DATA_ACK					0xFE				//Ӧ
#define SD_WRITE_ACK					0x05				//дӦ
//----ϵͳʱ----
//#define SD_TIMEOUT					100
//#define TIMEOUT							200
#define SD_TIMEOUT					255
#define TIMEOUT							255
/************************************************************************************************************
*     ƣWrite_Command_SD()
*     ܣSDSPIģʽ£SDд6ֽڵ
* ڲCMDָֽ
* ڲSD Ӧֵ
* ˵      SDһдֽڵ
* ʹ÷Write_Command_SD(CMD);
************************************************************************************************************/
unsigned char Write_Command_SD(unsigned char *CMD)
{
   unsigned char tmp=0;
   unsigned char i = 0;
   SD_CS_High();
   //-----ȷ8clock-----
   SD_Write_Byte(0xFF);
   SD_CS_Low();
   //-----д6ֽڵ֡-----
   SD_Write_Frame(CMD,6);
   //-----յһΣԵһֵ-----
   SD_Read_Byte();
   i = SD_TIMEOUT;
   do
   {
      tmp = SD_Read_Byte();
      i--;
   } while((tmp==0xff)&&i);
   return(tmp);
}
/************************************************************************************************************
*     ƣSD_Write_Sector
*     ܣSDSPIģʽ£SDУָλдָݡ
* ڲAddrĵַ
* 					*Ptrָдݵݻ
* 					FirstNumд׸ֽƫƵַ
* 					Num˴βҪдݸ				(FirstNum+Num<512)
* ڲ0дʧ
* 					1дɹ
* ʹ÷SD_Write_Sector(83241,buffer,0,100); 	 //83241д100ֽ
************************************************************************************************************/
unsigned char SD_Write_Sector(unsigned long Addr ,unsigned char *Ptr,unsigned int FirstNum,unsigned int Num)
{
	unsigned char temp=0;
	unsigned int EndNum = 0;
	unsigned int i=0;
	unsigned char CMD[6]={0};
	//----------
	CMD[0]=SD_CMD24;
	//-----32λַ------
	Addr = Addr <<9;													//sector = sector*512   ַתΪ߼ַ(עһҪ˴ת)
	CMD[1]=((Addr&0xFF000000)>>24);
	CMD[2]=((Addr&0x00FF0000)>>16);
	CMD[3]=((Addr&0x0000FF00)>>8);
	CMD[4]=Addr&0x000000FF;
	//-----CRCУ飬SPIģʽЧ-----
	CMD[5]=SD_SPI_CRC;
	//----ȴSDӦ----
	i=TIMEOUT;															//ʱֵ
	do{
		temp = Write_Command_SD(CMD);
		 i--;
	}while((temp != SD_COMMAND_ACK)&&i);		//ʱж
	if (i==0) 	return(0);													//ʱʧܴ
	//----շɴCLK----
	for(i=0;i<SD_WRITE_DELAY;i++)
	{
		SD_Write_Byte(SD_EMPTY_CLK);
	}
	//SD_Write_Frame(pTemp,SD_WRITE_DELAY);
	//-----ͷֽ-----
	SD_Write_Byte(SD_DATA_ACK);
//	//-----512ֽݣ----
	EndNum=FirstNum+Num;

	for(i=0;i<FirstNum;i++)
	{
		//-----д-----
		SD_Write_Byte(SD_EMPTY_DATA	);
	}
	SD_Write_Frame(Ptr,Num);				//дЧ
	for(i=0;i<512-EndNum;i++)
	{
		//-----д-----
		SD_Write_Byte(SD_EMPTY_DATA	);
	}
	//-----ֽڵУλ-----
	SD_Write_Byte(0xff);
	SD_Write_Byte(0xff);

	//-----жSDӦǷΪxxx00101b-------
	temp=SD_Read_Byte();
	temp =temp &0x01F;
	if(temp != SD_WRITE_ACK)
	{
		SD_CS_High();
		return(0);
	}
	//-------һֱCLKֱBUSY------
	i=TIMEOUT;														//ʱֵ
	do{
			 i--;
	}while(SD_Read_Byte() != 0xff &&i);					//ʱж
	if (i==0)
	{
		SD_CS_High();
		return(0);															//ʱʧܴ
	}
	//---ɹдݣƬѡCS------
	SD_CS_High();
	return 1;
}
/************************************************************************************************************
*     ƣSD_Read_Sector
*     ܣSDSPIģʽ£SDУָλôָݵ档
* ڲAddrĵַ
* 					*PtrָŶȡݵݻ
* 					FirstNumӸȡ׸ֽڵƫƵַ
* 					Num˴βҪȡݸ				(FirstNum+Num<512)
* ڲ0ȡʧ
* 					1ȡɹ
* ʹ÷SD_Read_Sector(83241,buffer,0,100); 	 //83241ж100ֽڣbuffer
************************************************************************************************************/
unsigned char SD_Read_Sector(unsigned long Addr ,unsigned char *Ptr,unsigned int FirstNum,unsigned int Num)
{
	unsigned char temp=0;
	unsigned int i=0;
	unsigned int EndNum=0;
	unsigned char CMD[6]={0};

	//-----17-----
	CMD[0]=SD_CMD17;
	//-----32λַ------
	Addr = Addr <<9;												//sector = sector*512   ַתΪ߼ַ
	CMD[1]=((Addr&0xFF000000)>>24);
	CMD[2]=((Addr&0x00FF0000)>>16);
	CMD[3]=((Addr&0x0000FF00)>>8);
	CMD[4]=Addr&0x000000FF;
	//-----CRCУ飬SPIģʽЧ-----
	CMD[5]=SD_SPI_CRC;

	//----ȴSDӦ----
	i=TIMEOUT;														//ʱֵ
	do{
	      temp = Write_Command_SD(CMD);
		 i--;
	}while((temp!=SD_COMMAND_ACK)&&i);		//ʱж
	if (i==0)
	{
		SD_CS_High();
		return(0);															//ʱʧܴ
	}
	//----ȴSDӦ--------------
	i=TIMEOUT;														//ʱֵ
	do{
		 temp = SD_Read_Byte();
		 i--;
	}while(( temp !=SD_DATA_ACK)&&i);				//ʱж
	if (i==0)
	{
		SD_CS_High();
		return(0);															//ʱʧܴ
	}
	//-----ȡָֽ-----
	EndNum=FirstNum+Num;
	for(i=0;i<FirstNum;i++)
	{
		//-----ն洢ֽ-----
			SD_Read_Byte();
	}
	SD_Read_Frame(Ptr,Num);			//ȡЧֽ
	for(i=0;i<512-EndNum;i++)
	{
		//-----ն洢ֽ-----
			SD_Read_Byte();
	}
	//-----ն CRC--Byte-----
	 SD_Read_Byte();
	 SD_Read_Byte();
	SD_CS_High();
	return (1);
}
/************************************************************************************************************
*     ƣSD_Init
*     ܣʼSDΪSPIģʽ
* ڲ
* ڲ0ʼʧ
* 					1ʼɹ
* ˵      ʼSDΪSPIģʽ
* ʹ÷SD_Init();
************************************************************************************************************/
unsigned char SD_Init()
{
	unsigned char temp =0 ;
	//-----ʼ֮ǰȽSPIΪ٣SPI_clk=300Kң-----
	SD_Low_Speed();
	//-----λSPI-----
	temp = SD_Reset();
	if(temp==0)
		return(0);
	//-----趨SDΪSPIȡģʽ-----
	temp = SD_Set_SPI();
	if(temp==0)
		return(0);
	//--ʼԺ󣬽SPIٶᵽ٣10Mhzңڿٶд-----
	SD_High_Speed();
	return(1);
}
/************************************************************************************************************
*     ƣSD_Reset()
*     ܣλSD
* ڲ
* ڲ0λSDʧ
* 					1λSDɹ
* ˵      ϵSDλSDģʽȸλΪSPIģʽ
* ʹ÷
************************************************************************************************************/
unsigned char SD_Reset()
{
	unsigned char i=0,temp = 0;
	unsigned char CMD[6] = {SD_CMD0,0x00,0x00,0x00,0x00,SD_CMD0_CRC};
	SD_CS_High();																	//CSƬѡʹ
	for(i=0;i<0x0f;i++)															//շ80CLK(10ֽڣ
	{
		SD_Write_Byte(SD_EMPTY_CLK);
	}

	i=TIMEOUT;																	//ʱֵ
	do{
		temp = Write_Command_SD(CMD);							//CMD0
		i--;
	}while((temp != SD_RESET_ACK) && i);						//ʱж
	if(i==0)
		return(0);																	//ʱʧܴ
	else
		return (1);
}
/************************************************************************************************************
*     ƣSD_Set_SPI()
*     ܣSDΪSPIģʽ
* ڲ
* ڲ0λSDʧ
* 					1λSDɹ
* ˵      ȸλܽSPIģʽ
* ʹ÷
************************************************************************************************************/
unsigned char SD_Set_SPI()
{
	unsigned char i=0,temp=0;
	unsigned char CMD[6]={0};
	//-----Ϊ4ֽ-----
	CMD[0]= SD_CMD1;
	CMD[1]= ((0x00ffc000 & 0xff000000) >>24);
	CMD[2]= ((0x00ffc000 & 0x00ff0000) >>16);
	CMD[3]= ((0x00ffc000 & 0x0000ff00) >>8);
	CMD[4]= 0x00ffc000 & 0x000000ff;
	CMD[5]= SD_SPI_CRC;

	i=TIMEOUT;																			//ʱֵ
	do{
	       CMD[0] = SD_CMD55;                  									//CMD55
	       temp = Write_Command_SD(CMD);   							//ȷ CMD55
	       //-----жǷΪSD-----
	       if(temp == 0x01)                 											//зӦ
	       {
//		//-----жϴ洢ֱִͣ߼-----
				 CMD[0] = SD_CMD1;                 								//CMD41
				 CMD[5] = 0xFF;
				 temp = Write_Command_SD(CMD); 						//CMD41м

				 CMD[0] = SD_CMD59;                 								//CMD41
				 CMD[5] = 0xFF;
				 temp = Write_Command_SD(CMD); 						//CMD41м

				 _nop();
				 if(temp == 0x00)
				 {
						SD_CS_High();														//CSƬѡ
				 }
//		//---------------------------------------------------
       }
	       //-----ΪMMC-----
	       else                             														//CMD55޷ӦķCMD1
	       {
				 CMD[0] = SD_CMD1;                 								//CMD1
				 CMD[5] = 0xFF;
				 temp = Write_Command_SD(CMD);    					//CMD1м
				 if(temp == 0x00)
				 {
						SD_CS_High();														//CSƬѡ
				 }
	       }
		i--;
	}while((temp !=SD_COMMAND_ACK)&&i);							//ʱж
	if(i==0)
		return(0);																			//ʱʧܴ
	else
		return (1);
}



